<?php
require_once(CARDS_DECK_FILE);
require_once(GAME_CONFIG_FILE);
require_once(PLACED_CARD_FILE);
require_once(UTILS_FILE);

class Player
{
	private $_id;
	private $_holding_cards;
	private $_board;
	private $_towers;
	
	private $_rules;
	
	public function __construct($id, $holding_cards, $board, $towers) {
		$this->_id = $id;
		if($holding_cards == null) {
			$this->_holding_cards = array();
		}
		else {
			$this->_holding_cards = $holding_cards;
		}
		$this->_board = $board;
		$this->_towers = $towers;
		
		$this->_rules = CardsDeck::Instance();
	}

	public function ID() { return $this->_id; }
	
	public function has_card($id) {
		foreach($this->_holding_cards as $card) {
			if($card == $id) {
				return True;
			}
		}
		return False;
	}
	
	public function is_lost() {
		$counter = 0;
		for($i = 0; $i < ROW_SIZE; $i++) {
			if($this->_towers[$i] <= 0) {
				$counter++;
			}
		}
		if($counter >= TOWER_TO_LOSE) {
			return True;
		}
		return False;
	}
	
	public function board_full() {
		for($i = 0; $i < ROW_SIZE; $i++) {
			for($j = 0; $j < COL_SIZE; $j++) {
				if($this->_board[$i][$j] == null) {
					return False;
				}
			}
		}
		return True;
	}
	
	public function row_full($row) {
		if($row >= ROW_SIZE) {
			return null;
		}
		for($j = 0; $j < COL_SIZE; $j++) {
			if($this->_board[$row][$j] == null) {
				return False;
			}
		}
		return True;
	}
	
	public function place_card($card_indx, $x, $y) {
		if(Utils::boundries_check($x, $y)) {
			if($this->cell($x, $y) == null) {
				if( ($card_indx-1 >= count($this->_holding_cards)) || ($card_indx-1 < 0) ) {
					Utils::Error("Error - Player::place_card - out of array!");
					return null;
				}
				$card_id = $this->_holding_cards[$card_indx-1];
				if($card_id == null) {
					Utils::Error("Error - Player::place_card - $card_indx not in deck!");
					return null;
				}
				if($this->has_card($card_id)) {
					$this->_board[$x][$y] = new PlacedCard($card_id, $this->_rules->card_hp($card_id));
					$this->remove_card($card_id);
					return true;
				}
				else {
					Utils::Error("Error - Player::place_card - $card_indx not in deck!");
					return null;
				}
			}
			else {
				Utils::Error("Error - Player::place_card - $x, $y is full in the board!");
				return null;
			}
		}
		else {
			Utils::Error("Error - Player::place_card - $x, $y not lagit cordinate!");
			return null;
		}
	}

	private function remove_card($card_id) {
		for($i = 0; $i < count($this->_holding_cards); $i++ ) {
			if($this->_holding_cards[$i] == $card_id) {
				unset($this->_holding_cards[$i]);
				$this->_holding_cards = array_values($this->_holding_cards);
				return true;
			}
		}
		Utils::Error("Error - Player::remove_card - $card_id not in deck!");
		return null;
	}
	
	public function cell($x, $y) {
		if(Utils::boundries_check($x, $y)) {
			return $this->_board[$x][$y];
		}
		else {
			Utils::Error("Error - Player::cell - $x, $y not lagit cordinate!");
			return null;
		}
	}

	public function deck_not_full() {
		return ( count($this->_holding_cards) < MAX_CARD_HOLDING );
	}
	
	public function draw_card() {
		if($this->deck_not_full()) {
			$this->_holding_cards[] = $this->_rules->random_card_id();
			return true;
		}
		else {
			Utils::Error("Error - Player::draw_card - player $this->_id deck is full!");
			return null;
		}
	}
	
        // op. claim to be hit in  ($dmg) value in row number ($row)
	public function take_damage($dmg, $row) {

            //for all card in a row, hit soldiers\towers untill dmg count == $dmg
            for($i = COL_SIZE-1; $i >= 0; $i--) {
                //if you have a card in place i 
                if($this->_board[$row][$i] != null) {
                    //Hit Soldier && get the remaining dmg of the attack to attack next one!
                    $transfer_dmg = $this->_board[$row][$i]->take_damage($dmg); 
                    if($transfer_dmg < 0) {             //kill, keep on going
                        $this->_board[$row][$i] = null;
                        $dmg = -$transfer_dmg;
                    }
                    else if($transfer_dmg > 0) {        //alive, stop
                        return true;
                    }
                    else if($transfer_dmg == 0) {       //kill, stop
                        $this->_board[$row][$i] = null;
                        return true;
                    }
                    else {
                        Utils::Error("in player: take damage");
                        return null;
                    }
                }
            }
            return $this->tower_damage($dmg, $row);
	}
	
	private function tower_damage($dmg, $row) {
		if($row > ROW_SIZE || $row < 0) {
			Utils::Error("Error - Player::tower_damage - row $row is out of border!");
			return null;
		}
		if($this->_towers[$row] <= 0) {
			return true;
		}
		$this->_towers[$row] -= $dmg;
		if($this->_towers[$row] <= 0) {
			$this->_towers[$row] = 0;
		}
		return true;
	}

	public function tower($num) {
		if(Utils::boundries_check($num, 0)) {
			return $this->_towers[$num];
		}
	}

	public function cards() {
		$ary = null;
		for($i = 0; $i < count($this->_holding_cards); $i++) {
			$ary[] = $this->_holding_cards[$i];
		}
		return $ary;
	}

	public function return_board_answer() {
		$str = "";
		for($i = 0; $i < ROW_SIZE; $i++) {
			for($j = 0; $j < COL_SIZE; $j++) {
				$tmp = $this->_board[$i][$j];
				if($tmp == null) {
					$str .= "xxxxxx";
				}
				else {
					$id = $tmp->ID();
					$hp = $tmp->HP();
					$format = "%1$03d";
					$str .= sprintf($format, $id);
					$str .= sprintf($format, $hp);
				}
			}
		}
		return $str;
	}
	
	public function return_towers_answer() {
		$str = "";
		for($i = 0; $i < ROW_SIZE; $i++) {
			$tmp = $this->_towers[$i];
			$format = "%1$03d";
			$str .= sprintf($format, $tmp);
		}
		return $str;
	}
	
	public function return_cards_answer() {
		$str = "";
		$i = 0;
		for($i = 0; $i < count($this->_holding_cards); $i++) {
			$tmp = $this->_holding_cards[$i];
			$format = "%1$03d";
			$str .= sprintf($format, $tmp);
		}
		for($j = $i; $j < MAX_CARD_HOLDING; $j++) {
			$str .= "xxx";
		}
		return $str;
	}
}

?>